#include "clientThread.hpp"
#include <chrono>
#include <iterator>
#include <string>
#include <thread>
#include <unistd.h>
#include <sstream>
#include <utility>
#include <vector>

using namespace std;

ClientThread::ClientThread(NetServer *server, int clientSkt)
{
    this->server = server;
    this->clientSkt = clientSkt;
    closeFlag = false;
}

void ClientThread::Run()
{
    clientThread = thread(&ClientThread::Loop, this);
}

void ClientThread::Loop()
{
    char recvBuf[1024] = {0};
    stringstream ss;
    while (!closeFlag)
    {
        if (topics.size() > 0)
        {
            MessageBag bag;
            bag.header = 'B';
            for (int i = 0; i < topics.size(); i++)
            {
                string value;
                server->GetValue(topics[i], value);
                bag.data.push_back(pair<string, string>(topics[i], value));
            }
            string encodeMessage = EncodeMessage(bag) + '\n';
            write(clientSkt, encodeMessage.data(), encodeMessage.size());
            this_thread::sleep_for(chrono::milliseconds(100));
            continue;
        }
        // 获取客户端的数据
        int num = read(clientSkt, recvBuf, sizeof(recvBuf));
        if (num > 0)
        {
            for (int i = 0; i < num; i++)
            {
                if (recvBuf[i] == '\n')
                {
                    // printf("recv client data : %s\n", ss.str().data());
                    MessageBag bag = DecodeMessage(ss.str());
                    if (bag.header == 'R')
                    {
                        topics.clear();
                        for (int i = 0; i < bag.data.size(); i++)
                        {
                            topics.push_back(bag.data[i].first);
                        }
                    }
                    else if (bag.header == 'W')
                    {
                        for (int i = 0; i < bag.data.size(); i++)
                        {
                            server->SetValue(bag.data[i].first, bag.data[i].second);
                        }
                    }
                    ss.str("");
                }
                else
                {
                    ss << recvBuf[i];
                }
            }
        }
        else if (num == -1)
        {
            perror("read from client fail");
            break;
        }
        else if (num == 0)
        {
            // 表示客户端断开连接
            printf("clinet closed...");
            break;
        }
    }
    close(clientSkt);
}

void ClientThread::Close()
{
    closeFlag = true;
    clientThread.join();
}

ClientThread::MessageBag ClientThread::DecodeMessage(std::string message)
{
    MessageBag bag;
    bag.header = message[1];
    message = message.substr(3);
    int index = 0;
    do
    {
        index = message.find_first_of(',');
        string pairStr = message.substr(0, index);
        int subIndex = pairStr.find_first_of(':');
        if (subIndex < 0)
            continue;
        string topic = pairStr.substr(0, subIndex);
        string value = pairStr.substr(subIndex + 1);
        bag.data.push_back(pair<string, string>(topic, value));
        message = message.substr(index + 1);
    } while (index > 0);
    return bag;
}

std::string ClientThread::EncodeMessage(ClientThread::MessageBag bag)
{
    stringstream ss;
    ss << '@' << bag.header << '=';
    for (int i = 0; i < bag.data.size(); i++)
    {
        ss << bag.data[i].first << ':' << bag.data[i].second;
        if (i < bag.data.size() - 1)
            ss << ',';
    }
    return ss.str();
}